package controllers;

import java.text.DateFormat;
import java.text.ParseException;
import java.util.*;

import models.*;
import play.mvc.Controller;

import java.text.*;

import com.sun.xml.internal.stream.Entity;

public class UserController extends Controller {
	/**
	 * 
	 * @author Mostafa Ali
	 * 
	 * 
	 */

	static long currentEntityID = 0;
	static long currentOrganizationID = 0;
	static boolean displayName = false;
	static boolean displayGender = false;
	static boolean displayEmail = false;
	static boolean allowAndOr = false;
	static String name = "";
	static String gender = "";
	static String email = "";
	static String andOr = "";

	/**
	 * A method that displays the criteria that the user is able to chose from
	 * to be able to filter users to invite them into either an organization or
	 * an entity. The 3 available criteria are the name, gender and email.
	 * 
	 * @author Mostafa Ali
	 * 
	 * @param entID
	 *            the ID of the entity that the user is currently browsing in.
	 * 
	 * @param orgID
	 *            the ID of the organization that the user is currently browsing
	 *            in.
	 * 
	 * @see apps/views/UserController/viewFilterUsersCriteria.html
	 * 
	 */

	public static void viewFilterUsersCriteria(long entID, long orgID) {
		currentOrganizationID = orgID;
		currentEntityID = entID;
		String userName = session.get("username");
		if (userName == null)
			return;
		User currentUser = User.find("byUsername", userName).first();
		if (currentUser == null)
			return;
		long entityIDToPass = currentEntityID;
		render(entityIDToPass);
	}

	/**
	 * A method that renders a view that asks the user to insert the data for
	 * the criteria that he has chosen to filter with in the previous view. This
	 * view allows the user an autocomplete feature for any of the three
	 * criteria that he/she has chosen to use.
	 * 
	 * @author Mostafa Ali
	 * 
	 * @param redirected
	 *            This is a boolean flag that tells the method whether the call
	 *            is coming from a redirection due to validation problems or
	 *            whether its coming normally after selecting the filtration
	 *            criteria.
	 * 
	 * @see apps/views/UserController/viewEnterFiltrationCriteria.html
	 * 
	 */

	public static void viewEnterFiltrationCriteria(boolean redirected) {
		if (redirected) {
			boolean displayNameField = displayName;
			boolean displayGenderField = displayGender;
			boolean displayEmailField = displayEmail;
			List<User> allUsers = User.findAll();
			List<String> userNames = new LinkedList<String>();
			List<String> genders = new LinkedList<String>();
			List<String> emails = new LinkedList<String>();
			if (displayNameField) {
				for (User user : allUsers) {
					if (!userNames.contains(user.name))
						userNames.add(user.name);
				}
			}
			if (displayGenderField) {
				for (User user : allUsers) {
					if (!genders.contains(user.gender))
						genders.add(user.gender);
				}
			}
			if (displayEmailField) {
				for (User user : allUsers) {
					if (!emails.contains(user.email))
						emails.add(user.email);
				}
			}
			boolean allowAndOr = UserController.allowAndOr;
			long entityIDToPass = currentEntityID;
			render(displayNameField, displayGenderField, displayEmailField,
					userNames, genders, emails, allowAndOr, entityIDToPass);
		} else {
			String names = params.get("name2");
			String gender = params.get("gender");
			String email = params.get("email");
			int numberOfCriteria = 0;
			if (names == null && gender == null && email == null) {
				validation.addError(names,
						"You must select at least one search criterion !",
						gender);
			}
			if (validation.hasErrors()) {
				params.flash();
				validation.keep();
				viewFilterUsersCriteria(currentEntityID, currentOrganizationID);
			} else {
				boolean displayNameField = false;
				boolean displayGenderField = false;
				boolean displayEmailField = false;
				List<User> allUsers = User.findAll();
				List<String> userNames = new LinkedList<String>();
				List<String> genders = new LinkedList<String>();
				List<String> emails = new LinkedList<String>();
				if (names != null) {
					numberOfCriteria++;
					displayNameField = true;
					for (User user : allUsers) {
						if (!userNames.contains(user.name))
							userNames.add(user.name);
					}
				}
				if (gender != null) {
					numberOfCriteria++;
					displayGenderField = true;
					for (User user : allUsers) {
						if (!genders.contains(user.gender))
							genders.add(user.gender);
					}
				}
				if (email != null) {
					numberOfCriteria++;
					displayEmailField = true;
					for (User user : allUsers) {
						if (!emails.contains(user.email))
							emails.add(user.email);
					}
				}
				displayName = displayNameField;
				displayGender = displayGenderField;
				displayEmail = displayEmailField;
				boolean allowAndOr = false;
				if (numberOfCriteria > 1)
					allowAndOr = true;
				UserController.allowAndOr = allowAndOr;
				long entityIDToPass = currentEntityID;
				render(displayNameField, displayGenderField, displayEmailField,
						userNames, genders, emails, allowAndOr, entityIDToPass);
			}
		}
	}

	/**
	 * A method that sends invitation emails and requests to one or more users
	 * chosen by the inviter. The users will then find these invitations in
	 * their list of requests and can approve them by accepting/ignoring the
	 * request.
	 * 
	 * @author Mostafa Ali
	 * 
	 * @see apps/views/UserController/sendInvitation.html
	 * 
	 * @throws ParseException
	 * 
	 */
	public static void sendInvitation() throws ParseException {
		String[] ids = params.getAll("ids");
		if (ids != null) {
			long[] userIDs = new long[ids.length];
			for (int i = 0; i < userIDs.length; ++i) {
				userIDs[i] = Long.parseLong(ids[i]);
			}
			String userName = session.get("username");
			if (userName == null) {
				return;
			}
			User organizer = User.find("byUsername", userName).first();
			if (organizer == null) {
				return;
			}
			EEntity entity = EEntity.find("byID", currentEntityID).first();
			if (entity == null) {
				return;
			}
			for (int i = 0; i < userIDs.length; ++i) {
				User user = User.find("byID", userIDs[i]).first();
				if (user == null)
					continue;
				Application
						.sendMail(
								"You are invited into this entity by "
										+ "the Organizer. Please either accept/reject the invitation",
								"Invitation into an Entity", user);
				Request requestForEntity = new Request(organizer, entity,
						entity.organization, user, new Date(),
						"Invitation to join entity");
				requestForEntity.save();
				user.invitations.add(requestForEntity);
				user.save();
			}
			long entityIDToPass = currentEntityID;
			render(entityIDToPass);
		} else {
			validation.addError("", "You didn't choose any users", "");
			validation.keep();
			doFilterUsers(UserController.name, UserController.gender,
					UserController.email, UserController.andOr, true);
		}
	}

	/**
	 * A method to filter users from the database according to the data entered
	 * for the search criteria chosen by the inviting user. The method checks
	 * whether the user has chosen to filter by an AND/OR query and performs the
	 * necessary queries accordingly. The method performs validations on the
	 * entered data and returns the user to re-enter the data in case any
	 * validations fail. The method is very flexible in allowing searching by
	 * LIKE and not by exact matches.
	 * 
	 * @author Mostafa Ali
	 * 
	 * @param name
	 *            name of the user to be searched for.
	 * 
	 * @param gender
	 *            gender of the user to be searched for.
	 * 
	 * @param email
	 *            email of the user to be searched for.
	 *            
	 * @param andOR
	 * 				determines whether the user has chosen to filter
	 * 				by AND or by OR.
	 * 
	 * @param redirected
	 *            a boolean variable to specify whether the call is a
	 *            redirection due to validation problems or a normal access to
	 *            the page to be rendered.
	 * 
	 * @see apps/views/UserController/doFilterUsers.html
	 * 
	 * 
	 * @throws ParseException
	 */

	public static void doFilterUsers(String name, String gender, String email,
			String andOr, boolean redirected) throws ParseException {
		UserController.name = name;
		UserController.gender = gender;
		UserController.email = email;
		UserController.andOr = andOr;
		List<User> resultingUsers = new ArrayList<User>();
		int countNotNull = 0;
		if (name != null) {
			name = name.toLowerCase();
			countNotNull++;
		}
		if (gender != null) {
			countNotNull++;
			gender = gender.toLowerCase();
		}
		if (email != null) {
			countNotNull++;
			email = email.toLowerCase();
		}
		if (andOr != null)
			andOr = andOr.toLowerCase();
		if (countNotNull == 1) {
			if (name == null && gender == null) {
				validation.required(email).message(
						"You must enter the email address.");
				validation.email(email).message(
						"The email is not of a suitable format");
				resultingUsers = User.find("byEmailLike", "%" + email + "%").fetch();
			} else {
				if (gender == null && email == null) {
					validation.required(name).message(
							"You must enter the name.");
					resultingUsers = User.find("byNameLike", "%" + name + "%").fetch();
				} else {
					if (name == null && email == null) {
						validation.required(gender).message(
								"You must enter the gender.");
						if (!gender.equalsIgnoreCase("male")
								&& !gender.equalsIgnoreCase("female"))
							validation.addError(gender,
									"The gender must be either male or female",
									gender);
						resultingUsers = User.find("byGender", gender).fetch();
					}
				}
			}
		} else {
			if (andOr == null) {
				validation.addError(andOr,
						"Please select whether you would like to filter"
								+ "by AND or by OR", andOr);
				params.flash();
				validation.keep();
				viewEnterFiltrationCriteria(true);
			}
			String filterKey = "";
			if (andOr.equalsIgnoreCase("and"))
				filterKey = "And";
			else
				filterKey = "Or";
			if (name != null && gender != null && email != null) {
				validation.required(name).message("You must enter the name.");
				validation.required(gender).message(
						"you must enter the gender.");
				validation.required(email).message("You must enter the email.");
				validation.email(email).message(
						"The email is not of a suitable format");
				if (!gender.equalsIgnoreCase("male")
						&& !gender.equalsIgnoreCase("female"))
					validation.addError(gender,
							"The gender must be either male or female", gender);
				if (filterKey.equals("And"))
					resultingUsers = User.find("byNameLikeAndGenderAndEmailLike",
							"%" + name + "%", gender, "%" + email + "%")
							.fetch();
				else {
					List<User> userMatchName = User.find("byNameLike",
							"%" + name + "%").fetch();
					List<User> userMatchGender = User.find("byGender", gender)
							.fetch();
					List<User> userMatchEmail = User.find("byEmailLike",
							"%" + email + "%").fetch();
					for (int i = 0; i < userMatchName.size(); ++i) {
						User user = userMatchName.get(i);
						if (!resultingUsers.contains(user))
							resultingUsers.add(user);
					}
					for (int i = 0; i < userMatchGender.size(); ++i) {
						User user = userMatchGender.get(i);
						if (!resultingUsers.contains(user))
							resultingUsers.add(user);
					}
					for (int i = 0; i < userMatchEmail.size(); ++i) {
						User user = userMatchEmail.get(i);
						if (!resultingUsers.contains(user))
							resultingUsers.add(user);
					}
				}
			} else {
				if (name == null) {
					validation.required(gender).message(
							"You must enter the gender.");
					validation.required(email).message(
							"You must enter the email.");
					validation.email(email).message(
							"The email is not of a suitable format");
					if (!gender.equalsIgnoreCase("male")
							&& !gender.equalsIgnoreCase("female"))
						validation.addError(gender,
								"The gender must be either male or female",
								gender);
					if (filterKey.equals("And"))
						resultingUsers = User.find("byGenderAndEmailLike", gender,
								"%" + email + "%").fetch();
					else {
						List<User> userMatchGender = User.find("byGender",
								gender).fetch();
						List<User> userMatchEmail = User.find("byEmailLike",
								"%" + email + "%").fetch();
						for (int i = 0; i < userMatchGender.size(); ++i) {
							User user = userMatchGender.get(i);
							if (!resultingUsers.contains(user))
								resultingUsers.add(user);
						}
						for (int i = 0; i < userMatchEmail.size(); ++i) {
							User user = userMatchEmail.get(i);
							if (!resultingUsers.contains(user))
								resultingUsers.add(user);
						}
					}
				} else {
					if (gender == null) {
						validation.required(name).message(
								"you must enter the name.");
						validation.required(email).message(
								"You must enter the email");
						validation.email(email).message(
								"The email is not of a suitable format");
						if (filterKey.equals("And")) {
							resultingUsers = User.find("byNameLikeAndEmailLike",
									"%" + name + "%", "%" + email + "%")
									.fetch();
						} else {
							List<User> userMatchName = User.find("byNameLike",
									"%" + name + "%").fetch();
							List<User> userMatchEmail = User.find(
									"byEmailLike", "%" + email + "%").fetch();
							for (int i = 0; i < userMatchName.size(); ++i) {
								User user = userMatchName.get(i);
								if (!resultingUsers.contains(user))
									resultingUsers.add(user);
							}
							for (int i = 0; i < userMatchEmail.size(); ++i) {
								User user = userMatchEmail.get(i);
								if (!resultingUsers.contains(user))
									resultingUsers.add(user);
							}
						}
					} else {
						if (email == null) {
							validation.required(name).message(
									"you must enter the name.");
							validation.required(gender).message(
									"You must enter the gender.");
							if (!gender.equalsIgnoreCase("male")
									&& !gender.equalsIgnoreCase("female"))
								validation
										.addError(
												gender,
												"The gender must be either male or female",
												gender);
							if (filterKey.equals("And"))
								resultingUsers = User.find("byNameLikeAndGender",
										"%" + name + "%", gender).fetch();
							else {
								List<User> userMatchGender = User.find(
										"byGender", gender).fetch();
								List<User> userMatchName = User.find(
										"byNameLike", "%" + name + "%").fetch();
								for (int i = 0; i < userMatchGender.size(); ++i) {
									User user = userMatchGender.get(i);
									if (!resultingUsers.contains(user))
										resultingUsers.add(user);
								}
								for (int i = 0; i < userMatchName.size(); ++i) {
									User user = userMatchName.get(i);
									if (!resultingUsers.contains(user))
										resultingUsers.add(user);
								}
							}
						}
					}
				}
			}
		}
		if (redirected) {
			int userCount = resultingUsers.size();
			boolean inviteToEntity = (currentEntityID != -1) ? true : false;
			long entityIDToPass = currentEntityID;
			render(resultingUsers, userCount, inviteToEntity, entityIDToPass);
		} else {
			if (validation.hasErrors()) {
				params.flash();
				validation.keep();
				viewEnterFiltrationCriteria(true);
			}
			int userCount = resultingUsers.size();
			boolean inviteToEntity = (currentEntityID != -1) ? true : false;
			long entityIDToPass = currentEntityID;
			render(resultingUsers, userCount, inviteToEntity, entityIDToPass);
		}

	}

	/**
	 * A method that adds an organization to the list of followed organizations
	 * for a certain user in case that the user choses to do so. It also add the
	 * user to the list of following users for the organization. The method
	 * therefore allows users to be notified about certain changes taking place
	 * in the organization.
	 * 
	 * @author Mostafa Ali
	 * 
	 * @param orgID
	 *            The organization to be followed
	 * 
	 * @see apps/views/Browse/viewOrganizaton
	 * 
	 */
	public static void userFollowOrganization(long orgID) {
		String userName = session.get("username");
		if (userName == null)
			return;
		User user = null;
		user = User.find("byUserName", userName).first();
		if (user == null)
			return;
		Organization organization = Organization.find("byID", orgID).first();
		if (organization == null)
			return;
		organization.followingUsers.add(user);
		user.followedOrgs.add(organization);
		user.save();
		organization.save();
		flash.success("You have successfuly followed this organization");
		Browse.viewOrganization(orgID);
		// confirmFollow(0);
	}

	/**
	 * A method that removes an organization from the list of followed
	 * organizations for a certain user in case that the user choses to do so.
	 * It also removes the user from the list of following users for the
	 * organization. The method therefore allows users to stop being notified
	 * about certain changes taking place in the organization.
	 * 
	 * @author Mostafa Ali
	 * 
	 * @param orgID
	 *            The organization to be unfollowed
	 * 
	 * @see apps/views/Browse/viewOrganizaton
	 * 
	 */

	public static void userUnfollowOrganization(long orgID) {
		String userName = session.get("username");
		if (userName == null)
			return;
		User user = null;
		user = User.find("byUserName", userName).first();
		if (user == null)
			return;
		Organization organization = Organization.find("byID", orgID).first();
		if (organization == null)
			return;
		organization.followingUsers.remove(user);
		organization.save();
		user.followedOrgs.remove(organization);
		user.save();
		flash.success("You have successfuly unfollowed this organization");
		Browse.viewOrganization(orgID);
		// confirmUnfollow(0);
	}

	/**
	 * A method that adds an entity to the list of followed entities for a
	 * certain user in case that the user choses to do so. It also add the user
	 * to the list of following users for the entity. The method therefore
	 * allows users to be notified about certain changes taking place in the
	 * entity.
	 * 
	 * @author Mostafa Ali
	 * 
	 * @param entityID
	 *            The entity to be followed
	 * 
	 * @see apps/views/Browse/viewEntity
	 *
	 */

	public static void userFollowEntity(long entityID) {
		String userName = session.get("username");
		if (userName == null)
			return;
		User user = null;
		user = User.find("byUserName", userName).first();
		if (user == null)
			return;
		EEntity entity = EEntity.find("byID", entityID).first();
		if (entity == null)
			return;
		entity.followingUsers.add(user);
		entity.save();
		user.followedEnts.add(entity);
		user.save();
		flash.success("You have successfuly followed this entity");
		Browse.viewEntity(entityID);
		// confirmFollow(1);
	}

	/**
	 * A method that adds a topic to the list of followed topics for a certain
	 * user in case that the user choses to do so. It also adds the user to the
	 * list of following users for the topic. The method therefore allows users
	 * to be notified about certain changes taking place in the topic.
	 * 
	 * @author Mostafa Ali
	 * 
	 * @param topicID
	 *            The topic to be followed
	 * 
	 * @see apps/views/Browse/viewTopic
	 * 
	 */

	public static void userFollowTopic(long topicID) {
		String userName = session.get("username");
		if (userName == null)
			return;
		User user = null;
		user = User.find("byUserName", userName).first();
		if (user == null)
			return;
		Topic topic = Topic.find("byID", topicID).first();
		if (topic == null)
			return;
		topic.followingUsers.add(user);
		topic.save();
		user.followedTopics.add(topic);
		user.save();
		flash.success("You have successfuly followed this topic");
		Browse.viewTopic(topicID);
		// confirmFollow(2);
	}

	/**
	 * A method that removes an entity from the list of followed entities for a
	 * certain user in case that the user choses to do so. It also removes the
	 * user from the list of following users for the entity. The method
	 * therefore allows users to stop being notified about changes taking place
	 * in the entity.
	 * 
	 * @author Mostafa Ali
	 * 
	 * @param entityID
	 *            The entity to be unfollowed
	 * 
	 * @see apps/views/Browse/viewEntity
	 * 
	 */
	
	public static void userUnfollowEntity(long entityID) {
		String userName = session.get("username");
		if (userName == null)
			return;
		User user = null;
		user = User.find("byUserName", userName).first();
		if (user == null)
			return;
		EEntity entity = EEntity.find("byID", entityID).first();
		if (entity == null)
			return;
		entity.followingUsers.remove(user);
		entity.save();
		user.followedEnts.remove(entity);
		user.save();
		flash.success("You have successfuly unfollowed this entity");
		Browse.viewEntity(entityID);
		// confirmUnfollow(1);
	}

	/**
	 * A method that removes a topic from the list of followed topics for a
	 * certain user in case that the user choses to do so. It also removes the
	 * user from the list of following users for the topic. The method therefore
	 * allows users to stop being notified about changes taking place in the
	 * topic.
	 * 
	 * @author Mostafa Ali
	 * 
	 * @param topicID
	 *            The topic to be unfollowed
	 * 
	 * @see apps/views/Browse/viewTopic
	 * 
	 */

	public static void userUnfollowTopic(long topicID) {
		String userName = session.get("username");
		if (userName == null)
			return;
		User user = null;
		user = User.find("byUserName", userName).first();
		if (user == null)
			return;
		Topic topic = Topic.find("byID", topicID).first();
		if (topic == null)
			return;
		user.followedTopics.remove(topic);
		user.save();
		topic.followingUsers.remove(user);
		topic.save();
		flash.success("You have successfuly unfollowed this topic");
		Browse.viewTopic(topicID);
		// confirmUnfollow(2);
	}

	/**
	 * A method that gets all of the followed organizations by a certain user to
	 * be displayed for the user.
	 * 
	 * @author Mostafa Ali
	 * 
	 * @see apps/views/UserController/getFollowedOrganizations
	 * 
	 * 
	 * */
	public static void getFollowedOrganizations() {
		String userName = session.get("username");
		if (userName == null)
			return;
		User user = null;
		user = User.find("byUserName", userName).first();
		if (user == null)
			return;
		List<Organization> followedOrgs = user.followedOrgs;
		int numberOfOrgs = followedOrgs.size();
		render(followedOrgs, numberOfOrgs);
	}

	/**
	 * A method that gets all of the followed entities by a certain user to be
	 * displayed for the user.
	 * 
	 * @author Mostafa Ali
	 * 
	 * @see apps/views/UserController/getFollowedEntities
	 * 
	 * 
	 * */

	public static void getFollowedEntities() {
		String userName = session.get("username");
		if (userName == null)
			return;
		User user = null;
		user = User.find("byUserName", userName).first();
		if (user == null)
			return;
		List<EEntity> followedEnts = user.followedEnts;
		int numberOfEnts = followedEnts.size();
		render(followedEnts, numberOfEnts);
	}

	/**
	 * A method that gets all of the followed topics by a certain user to be
	 * displayed for the user.
	 * 
	 * @author Mostafa Ali
	 * 
	 * @see apps/views/UserController/getFollowedTopics
	 * 
	 * 
	 * */

	public static void getFollowedTopics() {

		String userName = session.get("username");
		if (userName == null)
			return;
		User user = null;
		user = User.find("byUserName", userName).first();
		if (user == null)
			return;
		List<Topic> followedTopics = user.followedTopics;
		int numberOfTopics = followedTopics.size();
		render(followedTopics, numberOfTopics);
	}

	/**
	 * A simple method that displays to the user a view telling the user that he
	 * has successfuly followet the organization/entity/topic;
	 * 
	 * @param flag
	 *            flag that specifies the message displayed to the user
	 * 
	 */
	public static void confirmFollow(int flag) {
		render(flag);
	}

	public static void confirmUnfollow(int flag) {
		render(flag);
	}

	/**
	 * .mine A method to display the view that allows user filtration in the
	 * case that the organization is secret and the user requesting to filter
	 * and send invitations is the organization lead of the organization to
	 * which the users will be invited.
	 * 
	 * @param orgID
	 *            the ID of the org in the session
	 * 
	 * 
	 */
	public static void inviteToOrganization(long orgID) {
		Organization org = Organization.find("byID", orgID).first();
		String userName = session.get("username");
		if (userName == null)
			return;
		User user = User.find("byUsername", userName).first();
		if (user == null)
			return;
		boolean permitted = user.isOrganizationLead(orgID) && org.isSecret();
		render(permitted);
	}

	/**
	 * A method to idea developers to join an organization
	 * 
	 * @param rec
	 *            the list of users to invite
	 */

	public static void sendInvitationsToJoinOrg(List<User> rec) {
		Application
				.sendMail(
						"You are invited into this organization by "
								+ "the Organization lead. Please either accept/reject the invitation",
						"Invitation into an Organization", rec);
	}

	/**
	 * @author hesham380
	 * @param userTopic
	 *            one of the topics that will be related
	 * @param relateTopic
	 *            one of the topics that will be related
	 * @param relationName
	 *            name of the relation
	 * 
	 *            this method is used to related two topic together and add the
	 *            name of the relation
	 */

	public static void relatetoTopic(long userTopic, long relateTopic,
			String relationName) {

		String userName = session.get("username");
		if (userName == null)
			return;
		User user = null;
		user = User.find("byUsername", userName).first();
		if (user == null)
			return;
		// Topic topic = Topic.find("byName", relateTopic).first();
		int view = 0;

		// Topic uTopic = Topic.find("byName", userTopic).first();
		Topic uTopic = Topic.findById(userTopic);
		Topic topic = Topic.findById(relateTopic);

		if (topic == null || uTopic == null) {
			view = 0;
		}

		else if (relationName.equals("")) {

			view = -1;
			validation.addError(relationName,
					"You must enter name for relation");
			if (validation.hasErrors()) {
				params.flash();
				validation.keep();
				Browse.viewTopic(uTopic.id);

			}
		}

		else {

			Organization org = topic.entity.organization;
			if (user == null || (org.isSecret() && !org.isMember(user.id)))
				view = 1;
			else
				view = 2;
		}

		if (view == 2) {

			TopicRelationNames topicRelationName = new TopicRelationNames(
					relationName);
			topicRelationName.save();
			user.relateToTopic(uTopic, topic, topicRelationName);
			flash.success(uTopic.name + " and " + topic.name
					+ " are successfully related");
		}

		Browse.viewTopic(uTopic.id);

	}

	/**
	 * @author Hesham Al-Razaz
	 * 
	 * this method deletes the relation between 2 topics
	 *
	 * @param userTopic
	 *            one of the topics that will be removed from the relation
	 * @param relateTopic
	 *            one of the topics that will be removed from the relation
	 * 
	 *            
	 */
	public static void removeRelation(long userTopic, long relateTopic) {
		Topic uTopic = Topic.findById(userTopic);
		Topic topic = Topic.findById(relateTopic);
		String userName = session.get("username");
		if (userName == null)
			return;
		User user = null;
		user = User.find("byUsername", userName).first();
		if (user == null)
			return;
		if (uTopic == null || topic == null) {
			return;
		}

		else
			user.removeRelation(uTopic, topic);
		user.save();
		flash.success("Relation successfully removed");
		Browse.viewTopic(uTopic.id);

	}

	/**
	 *@author Yomna El Rashidi 
	 *
	 *sends invitation emails for idea developers to
	 *join an organization sent by the organization lead
	 * 
	 *@throws ParseException
	 * */

	public static void sendInvitationToJoinOrganization() throws ParseException {
		String[] ids = params.getAll("ids");
		if (ids != null) {
			long[] userIDs = new long[ids.length];
			for (int i = 0; i < userIDs.length; ++i) {
				userIDs[i] = Long.parseLong(ids[i]);
			}
			String userName = session.get("username");
			if (userName == null) {
				System.out.println("null username");
				return;
			}
			User organizationLead = User.find("byUsername", userName).first();
			if (organizationLead == null) {
				System.out.println("null organizer");
				return;
			}
			Organization org = Organization.find("byID", currentOrganizationID)
					.first();
			if (org == null) {
				System.out.println("null entity");
				return;
			}
			for (int i = 0; i < userIDs.length; ++i) {
				User user = User.find("byID", userIDs[i]).first();
				if (user == null)
					continue;
				Application
						.sendMail(
								"You are invited into this organization by "
										+ "the Organization Lead. Please either accept/reject the invitation",
								"Invitation into an Organization", user);
				Request requestForOrganization = new Request(organizationLead,
						org, user, new Date(),
						"Invitation to join organization");
				requestForOrganization.save();
				user.invitations.add(requestForOrganization);
				user.save();
			}
			long organizationID = currentOrganizationID;
			render(organizationID);
		} else {
			validation.addError("", "You didn't choose any users", "");
			validation.keep();
			doFilterUsers(UserController.name, UserController.gender,
					UserController.email, UserController.andOr, true);
		}
	}

	/**
	 * shows the user all plans related to him/her ,these plan includes plans
	 * he/she created and plans he/she is participating in their action items
	 * 
	 * @author Mostafa Fahim
	 * 
	 * @see @see app/views/UserController/getUserPlans.html
	 */

	public static void getUserPlans() {
		String userName = session.get("username");
		if (userName == null)
			return;
		User user = null;
		user = User.find("byUserName", userName).first();
		if (user == null)
			render(new ArrayList<Plan>(), new ArrayList<Plan>());
		else {
			List<Plan> ownPlans = user.plans;
			HashSet<Long> takenPlnIds = new HashSet<Long>();
			List<Plan> participateInPlans = new ArrayList<Plan>();
			List<ActionItem> participateInActionItems = user.actionItems;
			for (ActionItem aI : participateInActionItems) {
				if (!takenPlnIds.contains(aI.plan.id)) {
					takenPlnIds.add(aI.plan.id);
					participateInPlans.add(aI.plan);
				}
			}
			render(ownPlans, participateInPlans);
		}
	}
}
